package com.jvm.classloader;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 类加载器的双亲委托模型的好处：
 *      1.可以确保java核心库的类型安全：所有的java应用都至少会引用java.lang.Object类，也就是说
 *        在运行期java.lang.Object这个类会被加载到java虚拟机中，如果这个加载过程是由java应用自己
 *        的类的类加载器所完成的，那么很可能就会在jvm中存在多个版本的java.lang.Object类，而且这些
 *        类之间还是不兼容的，相互不可见的（正是命名空间在发挥的作用）。
 *        借助于双亲委托机制，java核心类库中的类的加载工作都是由启动类加载器来统一完成，从而确保了
 *        java应用所使用的都是同一个版本的java核心类库，它们之间是相互兼容的。
 *
 *      2.可以确保java核心类库所提供的类不会被自定义的类所替代。
 *
 *      3.不同的类加载器可以为相同名称（binary name）的类创建额外的命名空间。相同名称的类可以并存在
 *        java虚拟机中，只需要用不同的类加载器加载它们即可。不同类加载器所加载的类之间是不兼容的，这就
 *        相当于在java虚拟机内部创建了一个又一个互相隔离的java类空间，这类技术在很多框架中都得到了实际
 *        应用。
 */
public class MyTest21 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        MyTest16 loader1 = new MyTest16("loader1");
        MyTest16 loader2 = new MyTest16("loader2");

        loader1.setPath("C:\\Users\\John\\Desktop\\");
        loader2.setPath("C:\\Users\\John\\Desktop\\");

        Class<?> clazz1 = loader1.loadClass("com.jvm.classloader.MyPerson");
        Class<?> clazz2 = loader2.loadClass("com.jvm.classloader.MyPerson");

        System.out.println(clazz1.hashCode());
        System.out.println(clazz2.hashCode());

        System.out.println(clazz1 == clazz2);

        Object obj1 = clazz1.newInstance();
        Object obj2 = clazz2.newInstance();

        Method method = clazz1.getMethod("setMyPerson",Object.class);
        method.invoke(obj1,obj2);
    }
}
